package com.milepost.workflow.filter;

import com.alibaba.fastjson.JSONObject;
import com.milepost.workflow.common.constant.MilepostConstant;
import com.milepost.workflow.common.enums.DsKeyEnum;
import com.milepost.workflow.config.dynamicDs.DataSourceContextHolder;
import com.milepost.workflow.response.Response;
import com.milepost.workflow.response.ResponseHelper;
import com.milepost.workflow.user.entity.UsersEntity;
import com.milepost.workflow.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

import javax.servlet.FilterConfig;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;

/**
 * @author huarf
 * @Description 拦截除登录意外的所有请求，
 * 判断session中是否有用户信息，
 * 有则放行，
 * 没有则返回json数据
 * @create 2022-04-01 17:02
 */
@Slf4j
public class SessionFilter implements Filter {

    private UserService userService;

    public SessionFilter(UserService userService) {

        this.userService = userService;
    }

    /**
     * 不需要拦截的资源
     */
    private static List<String> notFilterResList = Arrays.asList("");

    /**
     * 登录页面地址
     */
    private static final String loginUrl = "/login/login.html?sexpire";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        try {

            String servletPath = request.getServletPath();
            //还可以指定其他的接口，                       登录页面和登录接口
            if (notFilterResList.contains(servletPath) || servletPath.startsWith("/login/")) {
                //放行
                filterChain.doFilter(request, response);
            } else {

                HttpSession session = request.getSession();

                UsersEntity userEntity = (UsersEntity) session.getAttribute(MilepostConstant.USER_SESSION_KEY);

                //已正常登录，放行
                if (userEntity != null) {
                    filterChain.doFilter(request, response);
                    return;
                }

                //session中无用户数据，尝试从url中取用户信息
                String userName = request.getParameter("userName");
                String pwd = request.getParameter("pwd");
                if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(pwd)) {
                    //利用url中的用户信息查询用户对象，放入session中，形成已登录状态
                    UsersEntity byUserNameAndPwd = null;
                    try {
                        DataSourceContextHolder.setDataSource(DsKeyEnum.USER.getKey());
                        byUserNameAndPwd = userService.getByUserNameAndPwd(userName, pwd);
                    } finally {
                        DataSourceContextHolder.clearDataSource();
                    }

                    if (byUserNameAndPwd != null) {
                        //用户信息正常，可以登录
                        session.setAttribute(MilepostConstant.USER_SESSION_KEY, byUserNameAndPwd);
                        //重新重定向到此资源，以此去掉url中的参数
                        response.sendRedirect(servletPath);
                        return;
                    } else {
                        //用户信息异常，无法登录，条状到登录页
                    }
                }

                //未登录，重定向到登录页
                log.warn("SessionFilter拦截到未登录用户");
                response.setStatus(HttpStatus.UNAUTHORIZED.value());

                //客户端期望返回的类型
                String accept = request.getHeader(HttpHeaders.ACCEPT);
                if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) {
                    //返回json数据
                    Response<String> failResponse = ResponseHelper.createFailResponse();
                    failResponse.setMsg("登录超时，请重新登录");
                    writeToResponse(response, failResponse);
                } else {
                    //返回html，重定向到登录页
                    response.sendRedirect(loginUrl);
                }
            }

        } catch (Exception e) {
            log.error("SessionFilter异常", e);
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            Response<String> exceptionResponse = ResponseHelper.createExceptionResponse(e);
            writeToResponse(response, exceptionResponse);
        }
    }

    /**
     * 设置跨域
     *
     * @param request
     * @param response
     */
    private void setCrossOrigin(HttpServletRequest request, HttpServletResponse response) {

        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("P3P", "CP=CAO PSA OUR");
    }

    @Override
    public void destroy() {

    }

    /**
     * 将 Response 对象写入到 response 中
     *
     * @param servletResponse
     * @param response
     * @throws IOException
     */
    protected void writeToResponse(ServletResponse servletResponse, Response<String> response) throws IOException {

        HttpServletResponse res = (HttpServletResponse) servletResponse;
        //设置Content-Type
        res.setContentType("application/json;charset=UTF-8");
        //设置charset
        res.setCharacterEncoding("UTF-8");
        //写入
        PrintWriter writer = res.getWriter();
        writer.write(JSONObject.toJSONString(response));
    }

}
